/*
 * serial.h
 *
 *  Created on: 2017年3月28日
 *      Author: chenshisheng
 */

#ifndef SERIAL_H_
#define SERIAL_H_

#include "main.h"
#include "ringbuffer.h"

#include "message_queue.h"

#define SERIAL_USE_USART1  0
#define SERIAL_USE_USART2  1
#define SERIAL_USE_USART3  0
#define SERIAL_USE_UART4   0
#define SERIAL_USE_UART5   0
#define SERIAL_USE_UART6   0
#define SERIAL_USE_LPUART1 0

#define SERIAL_NUM (SERIAL_USE_USART1 + \
                    SERIAL_USE_USART2 + \
                    SERIAL_USE_USART3 + \
                    SERIAL_USE_UART4  + \
                    SERIAL_USE_UART5  + \
                    SERIAL_USE_UART6  + \
                    SERIAL_USE_LPUART1)

#if SERIAL_NUM == 0
#   error "No UART device enabled!"
#endif

#define Serial_Max (SERIAL_NUM - 1)

#define SERIAL_FLAG_AUTO_LINE 0x00100

// 收发缓存大小
#define SERIAL_RX_BUFFER_SIZE 64
#define SERIAL_TX_BUFFER_SIZE 64

// 串口序号
typedef enum
{
#if SERIAL_USE_USART1
    Serial_1,
#endif

#if SERIAL_USE_USART2
    Serial_2,
#endif

#if SERIAL_USE_USART3
    Serial_3,
#endif

#if SERIAL_USE_UART4
    Serial_4,
#endif

#if SERIAL_USE_UART5
    Serial_5,
#endif

#if SERIAL_USE_UART6
    Serial_6,
#endif

#if SERIAL_USE_LPUART1
    Serial_LP1,
#endif
}Serial_t;

// 指定标准输入输出串口
#ifdef BOARD_WAR_SHIP
#   define STDIO_SERIAL Serial_1
#else
#   define STDIO_SERIAL Serial_2
#endif

typedef enum
{
    Serial_Ctl_Cmd,
    Serial_Ctl_Reconfig,
    Serial_Ctl_SetFlag,
    Serial_Ctl_ClearFlag,
    Serial_Ctl_ClearBuffer,
    Serial_Ctl_GetBuadRate,
    Serial_Ctl_RxCmd,
}Serial_Ctl_t;

typedef void (* Serial_Callback_t)(Serial_t serial);
typedef bool (* Serial_RxByteCallback_t)(Serial_t serial, uint8_t b);

void Serial_Init(void);
void Serial_IRQHandler(Serial_t serial);
void Serial_SetCallbacks(
        Serial_t serial,
        Serial_Callback_t onTxBegin,
        Serial_Callback_t onTxComplete,
        Serial_RxByteCallback_t onRxByte);
void Serial_GetCallbacks(
        Serial_t serial,
        Serial_Callback_t *onTxBegin,
        Serial_Callback_t *onTxComplete,
        Serial_RxByteCallback_t *onRxByte);
void Serial_SendByte(Serial_t serial, uint8_t b);
void Serial_SendByteWithoutBuffer(Serial_t serial, uint8_t b);
void Serial_Send(Serial_t serial, const void *data, unsigned int size);
void Serial_SendString(Serial_t serial, const char *str);
int Serial_RecvByte(Serial_t serial, uint8_t *byteOut);
int Serial_RecvByteWithoutBuffer(Serial_t serial, uint8_t *byteOut);
unsigned int Serial_Recv(Serial_t serial, void *data, unsigned int size, unsigned int timeoutMs);
void Serial_ClearTxBuffer(Serial_t serial);
void Serial_ClearRxBuffer(Serial_t serial);
int Serial_RecvLine(Serial_t serial, char buf[], unsigned int size, char end);
int Serial_IoCtl(int serial, int ctl, ...);

/// 自定义的printf所使用串口输出重定向接口
#define Serial_PutChar(c) Serial_SendByte(STDIO_SERIAL, c)
void Serial_Cmd(Serial_t serial, FunctionalState NewState);
void Serial_TestCmd(Serial_t serial, bool isEnable);
void Serial_OnTest(MsgQueue_Msg_t *msg);
void Serial_Config(Serial_t serial, LL_USART_InitTypeDef* USART_InitStruct);
const char *Serial_GetName(Serial_t serial);
void Serial_SetFlag(Serial_t serial, uint32_t flags);
void Serial_ClrFlag(Serial_t serial, uint32_t flags);
uint32_t Serial_GetBaudRate(Serial_t serial);

#endif /* SERIAL_H_ */
